//
//  CLEncoder.m
//  togetherLBS
//
//  Created by Phyllis Hu on 13-6-1.
//  Copyright (c) 2013年 celi. All rights reserved.
//  数据加密的工具类

#import "CLEncoder.h"
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonHMAC.h>

@implementation CLEncoder

static char a[64] = {
    '7', '1', '6', 'x', 'O', 's', 'S', 'b',
    'J', 'r', 'u', 'a', '3', 'v', 'P', 'T',
    'A', 'I', 'w', '2', 'V', 'e', 'Z', 'n',
    'K', 'o', '-', '5', 'm', '+', 'L', 'd',
    'Y', 'N', 'f', 'k', 'g', '0', 'M', 'h',
    'B', 'l', '4', 'G', 'F', 'c', 'q', 'D',
    'C', 'U', 'i', 't', 'Q', 'R', 'H', '8',
    'X', 'j', 'E', '9', 'z', 'p', 'y', 'W'};

static char b[62] = {
    '7', '1', '6', 'x', 'O', 's', 'S', 'b',
    'J', 'r', 'u', 'a', '3', 'v', 'P', 'T',
    'A', 'I', 'w', '2', 'V', 'e', 'Z', 'n',
    'K', 'o', 'y', '5', 'm', 'W', 'L', 'd',
    'Y', 'N', 'f', 'k', 'g', '0', 'M', 'h',
    'B', 'l', '4', 'G', 'F', 'c', 'q', 'D',
    'C', 'U', 'i', 't', 'Q', 'R', 'H', '8',
    'X', 'j', 'E', '9', 'z', 'p'};

static char* p[2] = {a,b};
static int aLen = sizeof(a)/sizeof(char);
static int bLen = sizeof(b)/sizeof(char);

+(NSInteger)getLenByVersion:(NSInteger)version
{
    NSInteger temp = -1;
    switch (version) {
        case V1:
            temp = aLen;
            break;
        case V2:
            temp = bLen;
            break;
        default:
            break;
    }
    return temp;
}
+(NSMutableArray *) base64toArrayById:(NSInteger)nId version:(NSInteger) version
{
    NSMutableArray *value = [[NSMutableArray alloc] init];
    long i = nId;
    NSInteger len = [CLEncoder getLenByVersion:version];
    while (i > 0) {
        long r = i % len;
        [value addObject:[NSNumber numberWithLong:r]];
        i = i/len;
    }
    return value;
}

+(NSString *)encodeLon:(double)lon byVersion:(NSInteger)version
{
    NSInteger nLon = 0;
    if (lon == 0) {
        return @"0";
    }
    if (lon < 0) {
        nLon = (180-lon)*pow(10, 6);
    }else{
        nLon = lon *pow(10, 6);
    }
    NSString *lonEncode = [CLEncoder encode:nLon byVersion:version];
    DLog(@"lon=%f,encode:%@",lon,lonEncode);
    return lonEncode;
}
+(NSString *)encodeLat:(double)lat byVersion:(NSInteger)version
{
    NSInteger nLat = 0;
    if (lat == 0) {
        return @"0";
    }
    if (lat < 0) {
        nLat = (90-lat)*pow(10, 6);
    }else{
        nLat = lat *pow(10, 6);
    }
    NSString *latEncode = [CLEncoder encode:nLat byVersion:version];
    DLog(@"lat=%f,encode:%@",lat,latEncode);
    return latEncode;
}

+(NSMutableString *)encode:(NSInteger)nId byVersion:(NSInteger)version
{
    NSMutableArray *values = [CLEncoder base64toArrayById:nId version:version];
    NSMutableString *sb = [[NSMutableString alloc] initWithCapacity:5];
    
    for (id i in values) {
        NSInteger nI = [i intValue];
        char key = p[version][nI];
        NSString *temp = [NSString stringWithFormat:@"%c",key];
        [sb insertString:temp atIndex:0];
    }
    return sb;
}

+(NSInteger)decodeByArray:(NSMutableArray *)base64 version:(NSInteger) version
{
    for (int i = 1; i<= (6-[base64 count]); i++) {
        [base64 insertObject:[NSNumber numberWithInt:0] atIndex:0];
    }
    NSInteger nId = 0;
    NSInteger size = [base64 count];
    NSInteger len = [CLEncoder getLenByVersion:version];
    for (int i = 0; i< size; i++) {
        NSInteger value = [[base64 objectAtIndex:i]integerValue];
        nId += (NSInteger)(value * pow(len, size - i - 1));
    }
    return nId;
}

+(NSInteger)char2Int:(char)c version:(NSInteger)version
{
    NSInteger len = [CLEncoder getLenByVersion:version];
    for (int i = 0; i < len; i++) {
        if (p[version][i] == c) {
            return i;
        }
    }
    DLog(@"解码错误：%c",c);
    return 0;
}

+(NSInteger)decode:(NSString *)value byVersion:(NSInteger)version
{
    if (value == nil || value.length == 0) {
        return 0;
    }
    NSMutableArray *values = [[NSMutableArray alloc] init];
    for (int i = 0; i< value.length; i++) {
        NSInteger ob = [CLEncoder char2Int:[value characterAtIndex:i]  version:version];
        [values addObject:[NSNumber numberWithInteger:ob]];
    }
    return [CLEncoder decodeByArray:values version:version];
}

/**
 *  对数据进行加密（那类数据加密？？）
 */
+ (NSString *)ASCEncode:(NSString *)str
{
    if (str == nil) {
        return nil;
    }
    
    NSMutableString *encodeStr = [[NSMutableString alloc] init];
    
    for (int i = 0; i<str.length; i++) {
        int aC = [str characterAtIndex:i] + 100;
        [encodeStr appendFormat:@"%x",aC];
    }
    return encodeStr;
}

/**
 *  对使用ASCEncode算法加密过后的数据进行解密
 */
+ (NSString *)ASCDecode:(NSString *)str
{
    if (str == nil) {
        return nil;
    }
    if ((str.length % 2) != 0) {
        DLog(@"数据有错！");
        return nil;
    }
    
    NSMutableString *encodeStr = [[NSMutableString alloc] init];
    
    for (int i = 0; i<str.length -1;) {
        char c = [str characterAtIndex:i];
        NSInteger first = c;
        if (first > 97){//小写字母 a b c d e f
            first -= (97-10);
        }else if (first > 65){//大写字母 A B C D E F
            first -= (65-10);
        }else if (first > 48){// 数字 0 - 9
            first -= 48;
        }
        
        char nC = [str characterAtIndex:i+1];
        NSInteger second = nC;
        if(second >97){
            second -= (97-10);
        }else if (second > 65){
            second -= (65-10);
        }else if (second > 48){
            second -= 48;
        }
        
        char oC = (first *16 + second - 100);
        [encodeStr appendFormat:@"%c",oC];
        
        i+=2;
    }
    return encodeStr;
}


+ (NSData *)encodeWithString:(NSString *)string
{
    NSMutableData *data=[NSMutableData dataWithData:[XJ_UUID dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:[@"00" dataUsingEncoding:NSUTF8StringEncoding]];
    [data appendData:[string dataUsingEncoding:NSUTF8StringEncoding]];
    [self encode:(char *)data.bytes size:(int)data.length-38 byUUID:(char *)[XJ_UUID UTF8String]];
    
    return data;
}

+ (void)encode:(char *)data size:(int)size byUUID:(char *)uuid
{
    int seed=0;
    char strSeed[4]={0};
    char dict[34]={0};
    
    // 生成随机种子
    seed=arc4random()%31+1;
    
    sprintf(strSeed, "%02x", seed);
    memset(data, 0x00, 38);
    memcpy(data, uuid, 36);
    memcpy(data+36, strSeed, 2);
    [self genDict:dict bySeed:(seed%32) andUUID:uuid];
    DLog(@"key: %d, dict: %s", seed, dict);
    
    [self blurData:(data+38) length:size byDict:dict];
}

+ (void)genDict:(char *)dict bySeed:(int)seed andUUID:(char *)uuid
{
    short limit=36-seed>=32? 32:(36-seed);
    
    memcpy(dict, uuid+seed, limit);
    if(limit<32)
    {
        memcpy(dict+limit, uuid, 32-limit);
    }
}

+ (void)blurData:(char *)data length:(int)size byDict:(char *)dict
{
    int i=0;
    
    while(i<size)
    {
        char *curr=data+i;
        *curr=CLCharBlur(*curr, CLMod8Bit(*(dict+(CLMod8Bit(i)))));
        i++;
    }
}

/**
 *  对字符串进行MD5加密
 */
+ (NSString *)MD5String:(NSString *)str
{
    const char *string = str.UTF8String;
    int length = (int)strlen(string);
    unsigned char bytes[CC_MD5_DIGEST_LENGTH];
    CC_MD5(string, length, bytes);
    
    NSMutableString *mutableString = @"".mutableCopy;
    for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [mutableString appendFormat:@"%02x", bytes[i]];
    }
//    DLog(@"MD5: %@", mutableString);
    return [NSString stringWithString:mutableString];
}
@end
